﻿using Edu.Abstracts;
using Edu.Entitys;
using Edu.Utilities;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.Linq;
namespace Edu.Services
{

    public class StudentRankInfoDto
    {
        public Guid UserId { get; internal set; }
        public string UserName { get; internal set; }
        public string Avatar { get; internal set; }
        public int? Score { get; internal set; }
        public DateTimeOffset? GradTime { get; internal set; }
    }
    public class TeacherRankInfoDto
    {
        public Guid UserId { get; internal set; }
        public string UserName { get; internal set; }
        public string Avatar { get; internal set; }
        public int? Score { get; internal set; }
    }




    public class RankAppService : WeChatAppServiceBase
    {
        private readonly IAppUserRepository appUserRepository;
        private IRepository<AppStudent, Guid> appStudents;
        private IRepository<AppTeacher, Guid> appTeachers;
        private IRepository<AppUserRank> appUserRank;

        public DefaultAsyncQueryableExecuter AsyncQueryableExecuter { get; }

        public RankAppService(IRepository<AppStudent, Guid> appStudents,
            IRepository<AppTeacher, Guid> appTeachers,
           IRepository<AppUserRank> appUserRank,
            IAppUserRepository appUserRepository)
        {
            this.appUserRepository = appUserRepository;
            this.appStudents = appStudents;
            this.appTeachers = appTeachers;
            this.appUserRank = appUserRank;
            AsyncQueryableExecuter = DefaultAsyncQueryableExecuter.Instance;
        }


        public async Task<PagedResultDto<StudentRankInfoDto>> GetStudentRank(PagedAndSortedResultRequestDto input)
        {
            var date = DateTimeOffset.Now;

            var query = this.appStudents as IQueryable<AppStudent>;

            input.Sorting = "AssessScore Desc,UserId Desc";

            var studentInfo = this.appStudents.Single(a => a.UserId == this.CurrentUser.Id.Value);

            query = query.Where(a => a.Status == StudentStatus.Grad && a.Job == studentInfo.Job);
            // query = query.Where(a => a.JoinYear == date.Year - 1 && a.Status == StudentStatus.Grad);
            var totalCount = await AsyncQueryableExecuter.CountAsync(query);

            query = query.ApplySorting(input);
            query = query.ApplyPaging(input);

            var entities = await AsyncQueryableExecuter.ToListAsync(query);

            var result = new List<StudentRankInfoDto>();
            foreach (var item in entities)
            {
                var user = await appUserRepository.GetAsync(item.UserId);

                result.Add(new StudentRankInfoDto
                {
                    UserId = user.Id,
                    UserName = user.Name,
                    Avatar = user.Avatar,
                    Score = item.AssessScore,
                    GradTime = item.GradTime,
                });
            }

            return new PagedResultDto<StudentRankInfoDto>(
                totalCount,
                result
            );
        }



        public double GetStudentRankNum(Guid studentId, JobType job)
        {
            var a = this.appUserRank as IEfCoreRepository<AppUserRank>;
            var data = a.DbSet.FromSql(
                "select b.UserId as `UserId`, b.rank AS `Rank` from (select `UserId`, @curRank := @curRank + 1 AS `rank`  FROM appstudents p, (SELECT @curRank:= 0) q WHERE `Status`=1 And `Job`={0} ORDER BY `AssessScore` DESC) AS b WHERE b.UserId = {1}", (int)job, studentId)
                .FirstOrDefault();
            return data.Rank;
        }

        public double GetTeacherRankNum(Guid teacherId, JobType job)
        {
            var a = this.appUserRank as IEfCoreRepository<AppUserRank>;
            var data = a.DbSet.FromSql(
                "select b.UserId as `UserId`, b.rank AS `Rank` from (select `UserId`, @curRank := @curRank + 1 AS `rank`  FROM appteachers p, (SELECT @curRank:= 0) q WHERE `Job`={0} ORDER BY `Rating` DESC ) AS b WHERE b.UserId = {1}",(int)job, teacherId)
                .FirstOrDefault();
            return data.Rank;
        }

        public async Task<PagedResultDto<TeacherRankInfoDto>> GetTeacherRank(PagedAndSortedResultRequestDto input)
        {
            var date = DateTimeOffset.Now;

            var query = this.appTeachers as IQueryable<AppTeacher>;

            input.Sorting = "Rating Desc,UserId Desc";

            var teacher = this.appTeachers.Single(a => a.UserId == this.CurrentUser.Id.Value);

            query = query.Where(a =>  a.Job == teacher.Job);

            var totalCount = await AsyncQueryableExecuter.CountAsync(query);

            query = query.ApplySorting(input);
            query = query.ApplyPaging(input);

            var entities = await AsyncQueryableExecuter.ToListAsync(query);

            var result = new List<TeacherRankInfoDto>();
            foreach (var item in entities)
            {
                var user = await appUserRepository.GetAsync(item.UserId);

                result.Add(new TeacherRankInfoDto
                {
                    UserId = user.Id,
                    UserName = user.Name,
                    Avatar = user.Avatar,
                    Score = item.Rating
                });
            }

            return new PagedResultDto<TeacherRankInfoDto>(
                totalCount,
                result
            );
        }

    }
}
